/*Copyright (C) 2009 Careil Baptiste

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifdef WIN32
# include <windows.h>
#else /* WIN32 */
# include <pthread.h>
# include <signal.h>
# include <errno.h>
# include <stdio.h>
#endif /* !WIN32 */
#include "Mutex.h"

////////////////////////////////////////////////////////////
/// Permet d'initialiser le mutex. Cette fonction doit être
/// appelée avant toutes les autres concernant les mutex.
////////////////////////////////////////////////////////////
void DLL_IMPEXP CSLP_InitMutex(CSLP_MUTEX *mutex)
{
#ifdef WIN32
  InitializeCriticalSection((CRITICAL_SECTION*)(mutex));
#else /* WIN32 */
  pthread_mutex_init((pthread_mutex_t*)(mutex), NULL);
#endif /* !WIN32 */
}

////////////////////////////////////////////////////////////
/// Permet de tenter le verrouillage d'un mutex. La fonction
/// laisse l'appelle desuite après son appelle.
////////////////////////////////////////////////////////////
int DLL_IMPEXP CSLP_TryToLockMutex(CSLP_MUTEX *mutex)
{
  int retval = CSLP_MUTEX_NONE;
#ifdef WIN32
  if (TryEnterCriticalSection((CRITICAL_SECTION*)(mutex)) == 0)
    {
      retval = CSLP_MUTEX_ALREADY_OWNED;
    }
#else /* WIN32 */
  if (pthread_mutex_trylock((pthread_mutex_t*)(mutex)) == EBUSY)
    {
      retval = CSLP_MUTEX_ALREADY_OWNED;
    }
#endif /* !WIN32 */
  return retval;
}

////////////////////////////////////////////////////////////
/// Permet le verrouillage d'un mutex. La fonction retourne
/// qu'une fois le mutex verrouillé, ou en cas d'erreur.
////////////////////////////////////////////////////////////
void DLL_IMPEXP CSLP_WaitToLockMutex(CSLP_MUTEX *mutex)
{
#ifdef WIN32
  EnterCriticalSection((CRITICAL_SECTION*)(mutex));
#else /* WIN32 */
  if (pthread_mutex_lock((pthread_mutex_t*)(mutex)) == EDEADLK)
    {
      raise(SIGABRT);
    }
#endif /* !WIN32 */
}

////////////////////////////////////////////////////////////
/// Permet de déverrouiller un mutex. Renvois une erreur
/// si le mutex n'était pas verrouillé par le thread.
////////////////////////////////////////////////////////////
void DLL_IMPEXP CSLP_UnlockMutex(CSLP_MUTEX *mutex)
{
#ifdef WIN32
  LeaveCriticalSection((CRITICAL_SECTION*)(mutex));
#else /* WIN32 */
  pthread_mutex_unlock((pthread_mutex_t*)(mutex));
#endif /* !WIN32 */
}

////////////////////////////////////////////////////////////
/// Permet de supprimer un mutex.
////////////////////////////////////////////////////////////
int DLL_IMPEXP CSLP_DeleteMutex(CSLP_MUTEX *mutex)
{
  int retval = CSLP_MUTEX_NONE;
  if (CSLP_TryToLockMutex(mutex) == CSLP_MUTEX_ALREADY_OWNED)
    {
      retval = CSLP_MUTEX_ALREADY_OWNED;
    }
  else
    {
      CSLP_UnlockMutex(mutex);
#ifdef WIN32
      DeleteCriticalSection((CRITICAL_SECTION*)(mutex));
#else /* WIN32 */
      if (pthread_mutex_destroy((pthread_mutex_t*)(mutex)) == EBUSY)
	{
	  printf("CSLP_DeleteMutex error : condition fail");
	}
#endif /* !WIN32 */
    }
  return retval;
}
